/**
 * 
 */
package logica.clases;

import logica.colecciones.Jugadores;
import logica.colecciones.Mapa;
import logica.datatypes.Dados.DataDados;
import logica.datatypes.Jugador.DataJugador_R1;
import logica.datatypes.Jugador.DataJugador_R11;
import logica.datatypes.Jugador.DataJugador_R17;
import logica.datatypes.Jugador.DataJugador_R5;
import logica.datatypes.Partida.DataPartida_R16;
import logica.datatypes.Partida.DataPartida_R4;
import logica.excepciones.JugadoresException;
import java.lang.Math;
import java.rmi.RemoteException;
import java.util.ArrayList;
import java.io.Serializable;
/**
 * @author pity
 *
 */
public class Partida implements Serializable{
	private String codigo;
	private Jugador jugadorProximo;
	private Jugador jugadorGanador;
	private Boolean enCurso;
	private Boolean iniciada;
	private Jugadores jugadores;
	private Mapa mapa;
	private final static long serialVersionUID = 1;
	/**
	 * @param codigo
	 * @param jugadorProximo
	 * @param jugadorGanador
	 * @param enCurso
	 * @param iniciada
	 * @param jugadores
	 * @param mapa
	 * @throws JugadoresException 
	 */
	public Partida(String codigo, Jugadores jugadores) throws JugadoresException {
		this.codigo = codigo;
		this.jugadores = jugadores;
		this.jugadorProximo = null;
		this.jugadorGanador = null;
		this.enCurso = false;
		this.iniciada = false;		
		this.mapa = null;
	}
	
	public String getCodigo() {
		return codigo;
	}
	public Jugador getJugadorProximo() {
		return jugadorProximo;
	}
	public Jugador getJugadorGanador() {
		return jugadorGanador;
	}
	public Boolean getEnCurso() {
		return enCurso;
	}
	public Boolean getIniciada() {
		return iniciada;
	}
	public Jugadores getJugadores() {
		return jugadores;
	}
	public Mapa getMapa() {
		return mapa;
	}
	public void setCodigo(String codigo) {
		this.codigo = codigo;
	}
	public void setJugadorProximo(Jugador jugadorProximo) {
		this.jugadorProximo = jugadorProximo;
	}
	public void setJugadorGanador(Jugador jugadorGanador) {
		this.jugadorGanador = jugadorGanador;
	}
	public void setEnCurso(Boolean enCurso) {
		this.enCurso = enCurso;
	}
	public void setIniciada(Boolean iniciada) {
		this.iniciada = iniciada;
	}
	public void setJugadores(Jugadores jugadores) {
		this.jugadores = jugadores;
	}
	public void setMapa(Mapa mapa) {
		this.mapa = mapa;
	}
	
	public DataJugador_R5[] listarNomJugadores(){
		return jugadores.listarNomJugadores();		
	}		
	
	public void distribuirFichas(Integer numJugador, Integer codPDest, Integer cantFichas){ //Creo que el UML nos quedo con los nombres (String) en lugar de codigos
		mapa.agregarCantFichas(codPDest, cantFichas);
		jugadores.quitarCantFichas(numJugador, cantFichas);
	}
	
	private static int aleatorio(int min,int max){
		return (int)(Math.random()*(max-min+1))+min;	
	}
	
	public void iniciarPartida(Mapa map){
//		this.mapa = map;	//esto hay q verlo!!!
		this.mapa = map.copiarMapa();
		int cantP = mapa.cantPaises(), cantJ = jugadores.cantJugadores(),codJugSorteado;
		int porAsignar[] = new int[cantJ];
		
		for (int i=0; i<cantJ; i++)	//Cargo un array con la cantidad de paises por jugador
		porAsignar[i] = cantP/cantJ;
		for (int i=0; i<cantP%cantJ; i++)
			porAsignar[i] += 1;
		
		for (int i=1; i<=cantP; i++){	//Recorro los paises y voy sorteandole un jugador a c/u
			Pais pais = mapa.find(i);
			do{
				codJugSorteado = aleatorio(1,cantJ);
			}
			while (porAsignar[codJugSorteado-1] < 1);
			Jugador jugador = jugadores.obtenerJugador(codJugSorteado);
			pais.setJugador(jugador);
			pais.setCantFichas(2);
			jugador.agregarPais(pais);
			porAsignar[codJugSorteado-1]--;
		}
		
		jugadorProximo = jugadores.primerJugador();
		enCurso = true;
		iniciada = true;
	}
	
	public void iniciarTurno(){
		Jugador jugador = jugadorProximo;
		int cantFichas = jugador.calculoCantFichas();
		if (cantFichas == 0){	//no preciso hacer un while ya que el siguienteEnTurno retorna el proximo jugador con paises
			jugador = jugadores.siguienteEnTurno(jugador.getNumero());
			cantFichas = jugador.calculoCantFichas();
		}
		jugador.setCantFichasDisp(cantFichas);
		jugador.setEnTurno(true);
		jugadorProximo = jugadores.siguienteEnTurno(jugador.getNumero());		
	}
	
	public DataJugador_R11[] cargaDataJugadores(){
		return jugadores.cargaDataJugadores_R11();
	} 
	
	public Jugador obtenerJugadorEnTurno(){
		return jugadores.obtenerJugadorEnTurno();
		
	} 
	
	public Boolean paisDelJugador(Integer codPais, int codJugador){
		return mapa.paisDelJugador(codPais, codJugador);		
	} 
	
	public void reagruparFichas(Integer codPOrig , Integer codPDest, Integer cantFichas){	//No se precisa el cod del jugador
		mapa.quitarCantFichas(codPOrig, cantFichas);
		mapa.agregarCantFichas(codPDest, cantFichas);
	}
	
	public DataPartida_R4 cargaDataPartida_R4(){
		DataPartida_R4 data = new DataPartida_R4(codigo);
		return data;
	} 
	 
	public DataPartida_R16 cargaDataPartida_R16(){
		String nomGanador, nomProximo;
		if (jugadorGanador != null)	//controlo que exista ganador, sino dejo nombre vacio
			nomGanador = jugadorGanador.getNombre();
		else
			nomGanador = "";
		if (jugadorProximo != null)	//controlo que exista proximo, sino dejo nombre vacio
			nomProximo = jugadorProximo.getNombre();
		else
			nomProximo = "";
		DataPartida_R16 data = new DataPartida_R16(codigo, nomProximo, nomGanador, enCurso, iniciada);
		return data;
	}
	
	public DataJugador_R17 [] listarJugadoresPartida(){ //en el UML recibe el codigo de la partida, quedo mal ya que no deberia recibir nada
		return jugadores.cargaDataJugadores_R17();			
	}                                                
	
	public void finalizarTurno(Integer codJugador){		
		if (jugadores.cantPaises(codJugador) == mapa.cantPaises())
			jugadorGanador = jugadores.obtenerJugador(codJugador);
		jugadores.finalizarTurno(codJugador);
	}          
	
	public Boolean existeJugador(String nomJugador){
		return jugadores.existeJugador(nomJugador);
	} 
	
	public Integer obtenerCodJugador(String nomJugador){
		return jugadores.obtenerCodJugador(nomJugador);
	}
	
	public Boolean jugadorEnTurno(Integer codJugador){
		return jugadores.jugadorEnTurno(codJugador);		
	}
	
	public Integer obtenerCodPais(String nomPais){
		return mapa.obtenerCodPais(nomPais);
	}
	
	public Integer obtenerCantFichasPais(Integer codPais){
		return mapa.obtenerCantFichasPais(codPais);
	} 
	
	public DataDados realizarAtaque(Integer codPOrig, Integer codPDest){
		Pais paisAtaque = mapa.find(codPOrig), paisDefensa = mapa.find(codPDest);
		int dadoAtaque = aleatorio(1, 6), dadoDefensa = aleatorio(1, 6);
		DataDados dados= new DataDados(dadoAtaque, dadoDefensa);
		if (dadoAtaque > dadoDefensa){
			if (paisDefensa.getCantFichas() > 1){
				paisDefensa.quitarFicha(1);
//				paisAtaque.agregarCantFichas(1);				
			}
			else{
				Jugador jugAtaque = paisAtaque.getJugador(), jugDefensa = paisDefensa.getJugador();
				jugadores.quitarPais(jugDefensa.getNumero(), codPDest);
				jugadores.agregarPais(jugAtaque.getNumero(), paisDefensa);
				paisDefensa.setJugador(jugAtaque);
				paisDefensa.setCantFichas(1);
				paisAtaque.quitarFicha(1);	
				if (jugAtaque.cantPaises()==mapa.cantPaises()){
					jugAtaque.setEnTurno(false);
					jugadorGanador = jugAtaque;
				}
			}				
		}
		else
			paisAtaque.quitarFicha(1);
		return dados;
	} 
	public ArrayList<Integer> codPaisesAsig(int codJugador){
		return jugadores.codPaisesAsig(codJugador);
	}
	
	public int cantJugadores(){
    	return jugadores.cantJugadores();
    }
	
	public boolean jugadorLogueado(int codJugador){
		return jugadores.jugadorLogueado(codJugador);
	}
	
	public void setJugadorLogueado(int codJugador, boolean log){
		jugadores.setJugadorLogueado(codJugador, log);
	}
	
	public DataJugador_R1 obtenerJugador(int codJugador){
		return jugadores.obtenerJugador(codJugador).toDataJugador_R1();
	}
	
	public boolean hayJugadorEnTurnoEnPEnCurso()throws RemoteException{
		return jugadores.hayEnTurno();
	}
}

